package com.innovation.client;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;

import com.innovation.message.ServerMessageProto.ServerMessage;

/**
 * 客戶端連接
 * @author Administrator
 *
 */
public class TcpClient extends AbstractClient {
	
	private static final Logger exceptionLog = Logger.getLogger("EXCEPTION");
	private static final Logger log = Logger.getLogger(TcpClient.class);
	
	//用来存放服务器端返回的数据
	public static Map<Channel, ServerMessage> responseData = new ConcurrentHashMap<Channel, ServerMessage>();
	
	private Bootstrap bootstrap = null;
	
	protected TcpClient(String host, int port, int bufferSendSize, int bufferRecvSize) {
		super(host, port, bufferSendSize, bufferRecvSize);
	}

	@Override
	public boolean connect() {
		if(bootstrap != null){
			log.info("reconnecting server, ip:" + host + ",port:" + port);
			destroy();
		}else{
			log.info("connecting server, ip:" + host + ",port:" + port);
		}
		
		bootstrap = new Bootstrap();
		bootstrap.group(new NioEventLoopGroup());
		bootstrap.channel(NioSocketChannel.class);
		bootstrap.option(ChannelOption.TCP_NODELAY, true);
		bootstrap.option(ChannelOption.SO_SNDBUF, bufferSendSize);
		bootstrap.option(ChannelOption.SO_RCVBUF, bufferRecvSize);
		bootstrap.handler(new TcpClientInitializer());
		
		try {
			ChannelFuture f = bootstrap.connect(host, port).sync();
			channel = f.channel();
			log.info("connect:"+channel);
			return true;
		} catch (Exception e) {
			exceptionLog.error(e);
			return false;
		}
	}

	@Override
	public ServerMessage sendAndRecv(ServerMessage msg) {
		if(channel == null || !channel.isOpen()){
			connect();
		}
		System.out.println("wait:"+channel+" hash="+channel.hashCode());
		channel.writeAndFlush(msg);
		synchronized (channel) {
			try {
				channel.wait(2000);//等待2s
			} catch (InterruptedException e) {
				log.error(e);
			}
		}
		return responseData.remove(channel);
	}

	/**
	 * 关闭客户端连接
	 */
	public void destroy(){
		if(channel != null){
			channel.close();
		}
		bootstrap.group().shutdownGracefully();
	}
	
	@Override
	public void send(ServerMessage msg) {
		channel.writeAndFlush(msg);
	}
}
